/*
 * GeoVISTA Center (Penn State, Dept. of Geography)
 * Copyright (c), 2003-2011,  Jin Chen and Alan M. MacEachren, GeoVISTA Center, Penn State University
 * Licensed under Simplified BSD License
 *
 *
 * @author: jin Chen 
 * @date: Mar 8, 2005$
 * @version: 1.0
 */
package edu.psu.geovista.app.pcp.plot.control.tools;

import edu.psu.geovista.app.pcp.DfPcp;
import edu.psu.geovista.app.pcp.plot.gui.BasicPcpUI;
import edu.psu.geovista.app.pcp.plot.layer.DataLayer;
import edu.psu.geovista.app.pcp.toolkits.Summarizer;
import edu.psu.geovista.app.pcp.toolkits.collection.CollectionUtils;
import edu.psu.geovista.app.pcp.toolkits.group.DataIDSet;
import edu.psu.geovista.app.plot.layer.Layer;
import edu.psu.geovista.app.visualclassifier.classify.v2.DefaultESVisualClassifier;
import edu.psu.geovista.classification.CategoryItf;
import edu.psu.geovista.classification.ClassificationResultItf;
import edu.psu.geovista.data.model.AppDataModel;
import edu.psu.geovista.ui.event.FreezeEvent;
import edu.psu.geovista.ui.event.SelectionEvent;

import java.awt.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;

public class   CategorySumDModeActor extends BasicDModeActor{
   private static final boolean DEBUG=false;
    //CategoryItf[] ctgs;
    HashMap categoryIDs=new HashMap();// 
    public CategorySumDModeActor(DataSelectTool datatool) {
        super(datatool);
    }


    public void fireIndicationChange(int id) {
          // 
            //this.clearSelection() ;    //wrong, select,any indicate, it clear last selection, but the selection is still on the screen.
            Integer indicateId=new Integer(id);
            //this.lastSelection.add(indicateId);
            HashSet ids = new HashSet();
            ids.add(indicateId);
            //convert summary ids to member ids and fire selection instead
            //this.getTool().fireSelectionChange(ids ) ; //not fire it anymore as it confusing
    }

    public void processIndication(int id, int x, int y) {
        //do nothing
    }
    //process external SelectionEvent, therefore do nothing
    public void processSelection(SelectionEvent e) {
        //do nothing
    }

    public void processFreeze(FreezeEvent e) {
        //todo not support yet
    }

    public void processClassification(ClassificationResultItf cr) {
             // 
             CategoryItf[] ctgs =  cr.getCategories() ;
             //this.getTool().updateModelForCategoryChange(ctgs); // 
             updateOnClassify(ctgs);

    }

    public void updateOnSwitchMode() {

        final DataSelectTool tool = this.getTool();
        BasicPcpUI ui = tool.getUI();

        DfPcp plot = (DfPcp) ui.getPlot();

        ClassificationResultItf resultItf = plot.getClassifyresult();
        if(resultItf==null)return;
        
        CategoryItf[] ctgs = resultItf.getCategories();///vc.getCategories();

        if(ctgs==null||ctgs.length ==0){
            ClassificationResultItf cr = plot.getClassifyresult();
            ctgs=cr.getCategories();
        }
        updateOnClassify(ctgs);

    }
    /**
     *  
     *  
     * @param colors
     */
    public void setDataLayerColors(Color[] colors) {
        //do noting, simply meet requirement of the interface
    }

    /**
     *  
     *  
     *  
     * - generated colors for category and their member
     * -  and related change
     * @param ctgs
     */
    private void updateOnClassify(CategoryItf[] ctgs){
        //this.setCtgs(ctgs);
        //prepare
        DataIDSet ids=null;
        final DataSelectTool tool = this.getTool();
        BasicPcpUI ui = tool.getUI();
        Color[] colors=null;
        edu.psu.geovista.data.model.AppDataModel dataModel=(AppDataModel) ui.getPlot().getDataModel() ;
        DataLayer srLayer=(DataLayer)ui.getLayer(Layer.TopData_LAYER );

        tool.clearSelection();
        tool.setStopActOnMouse(false);


        //update category memeber id
        //tool.seFirer.updateCtgMemberIds(ctgs);

        //update data model
        AppDataModel curModel=Summarizer.getCategorySummary(dataModel,ctgs);
        tool.updateServiceDataModel(curModel);
        updateCategoryIdsMap(curModel,ctgs);


        //vc.doClassification();  

        //category lines need to paint in bigger stroke
        srLayer.setStrongStrokeMode(true); //in summary mode, data is paint strongly

        //set colors for summary data
        HashSet IDs=new HashSet(); //summary data id need to be displayed
        int size=categoryIDs.size() ;//ctgs.length ;
                   //HashSet IDs=new HashSet();  //id of category to be displayed
                   // 
                   //    in the median dataModel, in which record ID is category ID.
                   colors=new Color[size];//color of categories
                   for (int i=0;i<size ;i++){
                       CategoryItf ctg=(CategoryItf) this.categoryIDs.get(new Integer(i)); //ctgs[i];
                       //if(ctg.isVisible() ){
                       IDs.add(new Integer(i));  //get id for the category
                       //}
                       colors[i]=ctg.getVisualInfo().getColor() ;// get the category color color
                   }

         /**
          *  
          *  
          *  
          *  
          */
         srLayer.setColors(colors);

        //set id to show
       ids=new  DataIDSet(IDs,DataIDSet.TYPE_CategoryData );//here the id is catogery id, not record id

       this.getTool().showDataGroup(ids);  //will do repainting

    }

    private void updateCategoryIdsMap(AppDataModel dataModel,CategoryItf[] ctgs){
        categoryIDs.clear();
         //final CategoryItf[] ctgs = this.getCtgs();
        final int numRecords = dataModel.getRowCount();


        for (int i=0;i<numRecords;i++){
            int recordIndex=i;
            final String rowName = dataModel.getRowName(i);
            //find category whose id.toString() = rowName
            for (int j=0;j<ctgs.length ;j++){

                final CategoryItf ctg = ctgs[j];
                if(ctg.getID().toString().equals(rowName) ){
                   this.categoryIDs.put(new Integer(recordIndex),ctg);
                }
            }

        }
         if(numRecords!=categoryIDs.size() ){
            if(DEBUG){
                assert false;
                System.err.println("Unable to find a category for some  IDs in dataModel");
            }
        }

    }


     public int[] getMemberIds(HashSet summaryIds){

        HashSet ctgSet=new HashSet();
        final AppDataModel dataModel = this.getTool().getService().getDataModel();
        final int[] ctgIds = CollectionUtils.convertToIntArray(summaryIds);
         // 
        for (int i=0;i<ctgIds.length ;i++){
            int ctgId=ctgIds[i]; // 
            final CategoryItf ctg = (CategoryItf) this.categoryIDs.get(new Integer(ctgId));//findCategoryById(rowName);
            if(ctg!=null){
                ctgSet.add(ctg);
            }
            else{
                if(DEBUG)
                    System.err.println("CategorySumDModeActor.getMemberIds unable to find category for index "+ctgIds[i]);


            }
        }
         //final Object[] objects = CollectionUtils.convertToArray(ctgSet);
          int[] ids = new int[0];
         if(ctgSet.size() >0){
           final CategoryItf[] ctgs = new CategoryItf[ctgSet.size()];
           int i=0;
           for (Iterator iterator = ctgSet.iterator(); iterator.hasNext();) {
               CategoryItf ctg = (CategoryItf) iterator.next();
               ctgs[i++]=ctg;
           }
           // 
           ids = DefaultESVisualClassifier.getMemberIds(ctgs);
         }
         return ids;
     }


}
